package com.wsz.security.controller;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wsz.security.pojo.Role;
import com.wsz.security.pojo.User;
import com.wsz.security.service.RoleService;
import com.wsz.security.service.UserService;
import com.wsz.security.utils.JwtUtils;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Arrays.stream;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;

@RequestMapping("/api")
@RestController
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    private final RoleService roleService;
    private final PasswordEncoder passwordEncoder;

    @GetMapping("/users")
    public ResponseEntity<List<User>> getUsers(){
        return ResponseEntity.ok().body(userService.getUserList());
    }

    @PostMapping("/user/save")
    public ResponseEntity<Boolean> saveUser(@RequestBody User user){
        URI uri = URI.create(ServletUriComponentsBuilder.fromCurrentContextPath().path("/api/user/save").toUriString());
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        System.out.println(user.getPassword());
        return ResponseEntity.created(uri).body(userService.save(user) ) ;
    }

    @PostMapping("/role/save")
    public ResponseEntity<Boolean> saveRole(@RequestBody Role role){
        URI uri = URI.create(ServletUriComponentsBuilder.fromCurrentContextPath().path("/api/role/save").toUriString());
        return ResponseEntity.created(uri).body(roleService.save(role));
    }

    @PostMapping("/role/addtouser")
    public ResponseEntity<?> saveRole(@RequestBody RoleToUserForm form){
        userService.addRoleToUser(form.getUsername(),form.getRoleName());
        return ResponseEntity.ok().build();
    }

    @GetMapping("/test")
    private String[] test(){
        List<String> list = new ArrayList<>();
        list.add("a");list.add("b");
        String acs = JwtUtils.createAccessToken("wsz", "/test", list);
        String reh = JwtUtils.createRefreshToken("wsz", "/test");
        DecodedJWT acsd = JwtUtils.parseToken(acs);
        DecodedJWT rehd = JwtUtils.parseToken(reh);
        return acsd.getClaim("roles").asArray(String.class);
    }

    @PostMapping("/token/refresh")
    public void refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String header = request.getHeader(AUTHORIZATION);
        if(header != null && header.startsWith("Bearer ")){
            try{
                String refresh_token = header.substring("Bearer ".length());
                DecodedJWT decodedJWT = JwtUtils.parseToken(refresh_token);

                String username = decodedJWT.getSignature();

                User user = userService.getUserByUserName(username);

                String access_token = JwtUtils.createAccessToken(username,request.getRequestURI(),user.getRoles().stream().map(Role::getName).collect(Collectors.toList()));

                Map<String,String> tokens = new HashMap<>();
                tokens.put("access_token",access_token);
                tokens.put("refresh_token",refresh_token);
                response.setContentType("application/json;UTF-8");
                new ObjectMapper().writeValue(response.getOutputStream(),tokens);

            }catch (Exception e){
                response.setHeader("error",e.getMessage());
                response.setStatus(403);
                Map<String,String> error = new HashMap<>();
                error.put("error_msg",e.getMessage());
                response.setContentType("application/json;UTF-8");
                new ObjectMapper().writeValue(response.getOutputStream(),error);
            }
        }else{
            throw new RuntimeException("刷新令牌丢失");
        }
    }
}

@Data
class  RoleToUserForm {
    private String username;
    private String roleName;
}
